home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / qdeck / kern / scale.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-11  |  7.8 KB  |  237 lines

  1. /*----------------------------------------------------------------------*/
  2. /*                                    */
  3. /*  Sample usage of scalable font fractional spacing and kerning.    */
  4. /*                                    */
  5. /*  This file demonstrates how scalable fonts can be used in the    */
  6. /*  DESQview/X environment.  It emphasises how fractional spacing    */
  7. /*  and kerning are performed.                        */
  8. /*                                    */
  9. /*----------------------------------------------------------------------*/
  10.  
  11. #include <stdio.h>
  12. #if defined(_HIGHC_)
  13. #include <stdlib.h>
  14. #endif
  15. #include <X11/Xmd.h>
  16. #include <X11/X.h>
  17. #include <X11/Xos.h>
  18. #include <X11/Xlib.h>
  19. #include <X11/Xutil.h>
  20. #include <X11/Xatom.h>
  21.  
  22.  
  23.  
  24. typedef struct KERNPAIRtag
  25. {
  26.   char chLeft;
  27.   char chRight;
  28.   INT32 xKernOffset;
  29. } KERNPAIR;
  30.  
  31.  
  32. Display          *dpy;
  33. int                  screen;
  34. Window             root;
  35. GC             gcBase;
  36. Window             winMain;
  37. KERNPAIR         *pKernBase;
  38. XFontStruct         *xfn;
  39.  
  40.  
  41. /*----------------------------------------------------------------------*/
  42. /*        BASIC X OPERATIONS                    */
  43. /*----------------------------------------------------------------------*/
  44.  
  45. main ()
  46. {
  47. XSetWindowAttributes xswa;
  48.  
  49.   dpy            = XOpenDisplay (NULL);
  50.   screen        = DefaultScreen(dpy);
  51.   root            = RootWindow(dpy,screen);
  52.   gcBase        = DefaultGC(dpy,screen);
  53.   winMain        = XCreateSimpleWindow (dpy, root, 0, 0, 500, 100, 0, 0L, 15L);
  54.   xswa.event_mask    = ExposureMask;
  55.   XChangeWindowAttributes (dpy, winMain, CWEventMask, &xswa);
  56.   XMapWindow (dpy, winMain);
  57.   InitText ("Times Roman-Medium-R", 24);
  58.  
  59.   while (1)
  60.   {
  61.   XEvent xe;
  62.  
  63.     XNextEvent (dpy,&xe);
  64.     switch (xe.type)
  65.     {
  66.       case Expose:
  67.     DrawText (10, 50, "This is the string to be printed.");
  68.     break;
  69.  
  70.       case DestroyNotify:
  71.     ClearText ();
  72.     break;
  73.     }
  74.   }
  75. }
  76.  
  77.  
  78. /*----------------------------------------------------------------------*/
  79. /*    SAMPLE CODE FOR FRACTIONAL SPACING AND KERNING            */
  80. /*----------------------------------------------------------------------*/
  81.  
  82.  
  83. /*----------------------------------------------------------------------*/
  84. /*    LOAD FONT AND READ KERNING PAIRS                */
  85. /*----------------------------------------------------------------------*/
  86.  
  87. InitText (char *pszFont, int PointSize)
  88. {
  89. char szName[256];
  90. int xRes;
  91. int yRes;
  92. Atom atomKernLabel, atomKernVar;
  93. XGCValues values;
  94. KERNPAIR *pKern;
  95. Atom atomType;
  96. int iFormat;
  97. long cItems;
  98. long bytes_after;
  99. char *pProp;
  100. char *pPropBase;
  101. int  cProps;
  102.  
  103.   xRes = 75;
  104.   yRes = 75;
  105.   sprintf (szName, "-Adobe-%s-Normal--*-%d-%d-%d-*-*-*-Adobe",
  106.         pszFont, PointSize*10, xRes, yRes);
  107.  
  108.   xfn = XLoadQueryFont (dpy, szName);               /* load the font     */
  109.   if (xfn)
  110.   {
  111.     values.font = xfn->fid;
  112.     XChangeGC (dpy, gcBase, GCFont, &values);
  113.  
  114.     /* Now we want to grab the kerning pairs.  This is done by looking at the */
  115.     /* font property 'KERNING_PAIRS' to find the root windows property name.  */
  116.     /* The root property is next examined to extract the needed pairs.    The   */
  117.     /* pairs are transferred into an array.                      */
  118.  
  119.     atomKernLabel = XInternAtom (dpy, "KERNING_PAIRS", 0);/* enumerate prop */
  120.     XGetFontProperty (xfn, atomKernLabel, &atomKernVar);  /* grab root name */
  121.     XGetWindowProperty (dpy, root, atomKernVar, 0, 8192,  /* get the info   */
  122.         False, AnyPropertyType, &atomType, &iFormat, &cItems, &bytes_after, &pProp);
  123.     pPropBase = pProp;
  124.     cProps = *(INT16 *)pProp;     pProp+=2;    /* get number of properties */
  125.     pKern = (KERNPAIR *)malloc (sizeof(KERNPAIR) * (cProps+1));
  126.     pKernBase = pKern;
  127.     while (cProps--)
  128.     {
  129.       pKern->chLeft     = *pProp++;          /* left character in pair */
  130.       pKern->chRight     = *pProp++;         /* right character in pair */
  131.       pKern->xKernOffset = (INT32)(*(INT16 *)pProp) + ((INT32)(*(INT16 *)(pProp+2)))*65536L;
  132.       pProp += 4;
  133.       pKern++;
  134.     }
  135.     pKern->chLeft      = 0;                   /* mark end of table */
  136.     pKern->chRight     = 0;
  137.     pKern->xKernOffset = 0;
  138.  
  139.     XFree (pPropBase);                   /* we are done with the data */
  140.   }
  141. }
  142.  
  143.  
  144. /*----------------------------------------------------------------------*/
  145. /*    UNLOAD FONT AND KERNING PAIRS                    */
  146. /*----------------------------------------------------------------------*/
  147.  
  148. ClearText ()
  149. {
  150.   free (pKernBase);                      /* free kerning stuff */
  151.   XFreeFont (dpy, xfn);                  /* get rid of font */
  152. }
  153.  
  154. /*----------------------------------------------------------------------*/
  155. /*    FIND PAIR OF CHARACTERS IN KERNING ARRAY            */
  156. /*----------------------------------------------------------------------*/
  157.  
  158. /* This routine just does a simple sequential search to find the kerning */
  159. /* pair.  A better implementation would be to sort the array and perform */
  160. /* binary searches.                             */
  161.  
  162. INT32 LookupKern (char chLeft, char chRight)
  163. {
  164. KERNPAIR *pKern;
  165.  
  166.   pKern = pKernBase;
  167.   while (pKern->chLeft)
  168.   {
  169.     if ((pKern->chLeft == chLeft) && (pKern->chRight == chRight))
  170.       return (pKern->xKernOffset);                /* return delta */
  171.     pKern++;
  172.   }
  173.   return (0L);                        /* no pair -> delta = 0 */
  174. }
  175.  
  176. /*----------------------------------------------------------------------*/
  177. /*    OUTPUT ONE LINE OF TEXT WITH KERNING + FRACTIONAL SPACING    */
  178. /*----------------------------------------------------------------------*/
  179.  
  180. /* This routine performs fractional spacing and kering as described    */
  181. /* in the documentation.  A series of XTextItem text chunks is output    */
  182. /* with delta "corrections" to compensate for the difference between    */
  183. /* rouded integer spacing and fractional spacing.            */
  184.  
  185. DrawText (int xPos, int yPos, char *pszText)
  186. {
  187. char chPrev;            /* previous character                */
  188. XTextItem ati[100];        /* XTextItem array for cummulation        */
  189. int cItems;            /* count of XTextItem entries            */
  190. INT16 xPosRound;        /* running x position as rounded integer    */
  191. INT32 xPosFixed;        /* running x position as 16.16 fixed nota'n */
  192. char *pszBase;            /* running pointer to base of text chunk    */
  193. INT16 DeltaInt;         /* rounded integer character width        */
  194. INT16 DeltaFrac;        /* signed fractional part of character wid. */
  195. INT16 xPosCheck;        /* variable fo comparing widths         */
  196. int  cChars;            /* number of charcters in XTextItem entry   */
  197.  
  198.   cChars    = 0;        /* initialize some stuff            */
  199.   chPrev    = 0;
  200.   xPosRound = 0;
  201.   xPosFixed = 0;
  202.   cItems    = 0;
  203.   pszBase   = pszText;
  204.   ati[0].delta    = 0;
  205.  
  206.   while (*pszText)
  207.   {
  208.     xPosFixed += LookupKern (chPrev, *pszText);  /* make kerning adjustment */
  209.     xPosCheck  = (INT16)((xPosFixed+32768L)>>16);      /* get round (16.16) */
  210.     if (xPosCheck != xPosRound)           /* is "correction" necessary? */
  211.     {
  212.       ati[cItems].chars   = pszBase;    /* sequence of characters to output */
  213.       ati[cItems].nchars  = cChars;      /* number of characters to output */
  214.       ati[cItems+1].delta = xPosCheck - xPosRound; /* how much of an adjmnt */
  215.       ati[cItems].font      = 0;         /* we want to use the current font */
  216.       xPosRound = xPosCheck;         /* "correct" the running rounded x pos */
  217.       pszBase    = pszText;         /* next text chunk will start here */
  218.       cChars    = 0;                  /* reset count for next chunk */
  219.       cItems++;                  /* increment XTextItem counter */
  220.     }
  221.     DeltaInt   = xfn->per_char[(INT16)*pszText - xfn->min_char_or_byte2].width;
  222.     DeltaFrac  = xfn->per_char[(INT16)*pszText - xfn->min_char_or_byte2].attributes;
  223.     xPosRound += DeltaInt;               /* update running x counters */
  224.     xPosFixed += (((INT32)DeltaInt)<<16) + (INT32)DeltaFrac;
  225.     cChars++;                 /* note that (INT32)DeltaFrac is signed */
  226.     chPrev = *pszText++;    /* so that it can both lower and raise DeltaInt */
  227.   }
  228.   ati[cItems].chars  = pszBase;            /* final XTextItem chunk */
  229.   ati[cItems].nchars = cChars;
  230.   ati[cItems].font   = 0;
  231.   cItems++;
  232.  
  233.   /* now, we actually print out the results of the above calculations    */
  234.  
  235.   XDrawText   (dpy, winMain, gcBase, xPos, yPos, ati, cItems);
  236. }
  237.